Javascript 是一個什麼樣的語言?
這意思是指 JS 不需要在變數定義時就確定只能使用哪一種型別,它可以執行的過程中轉換型別
舉例來說:
let foo = 100;
console.log(typeof(foo)); // Number
foo = 'string';
console.log(typeof(foo)); // String
foo = true;
console.log(typeof(foo)); // Boolean
如果是典型的靜態語言,像是 C# 或 JAVA,則會在型別管理十分嚴格,在宣告時就需要有明確定義,且不可隨意轉換。
這意思是指 JS 編譯器在型別檢查上較為寬鬆,可以允許隱性型別的轉換。
舉例來說:
let foo = "welcome to day"
let foo_number = 2;
console.log(foo + foo_number); // welcome to day2
console.log(typeof(foo + foo_number)); // String
Javascript 定義了七種內建型別,其中又可以拆分為 基本型別(Primitive Data Type) 跟 物件型別(Object)
特別的地方:
typeof(null)
會卻呈現 Objecttypepof(function(){})
是得到 function(){},而不是 Objecttypeof(NaN)
是得到 number,因為 NaN 是屬於無效的數字接下來,要來介紹等於,在 JS 中 比較的方法 有兩種方式 == 和 ===
關於 ==
,也可以說是寬鬆相等(loose equals),在 JS 運作中會去比較雙方,然後去自動轉型成同型別的值,再去進行比較是否相等。
下張圖展示在 基本型別 間 == 的運作模式:
關於 ===
,也可以說是嚴格相等(strict equals),不允許強轉型會直接比較是否相等。
特別的地方:
1.null == undefined
會呈現 true
2.NaN 永遠不等於自己,NaN == NaN
以及 NaN === NaN
會呈現 false
在 ES5 時,JS 只有兩種宣告變數的方法,分別是 var 跟 function;而在 ES6,添加了 let(變數),const(常數), import, class 這幾種方式。這邊主要會比較 let, const 與 var 的作用域(Scope)間的差異以及新手可能會踩到的一些雷。
常數(唯讀),在一宣告的時候就必須要給值,而且不可以再重複 assign 值
但這裡要注意,並非變量的值不可以變動,而是變量指向記憶體的位址不可以變動。而基本型別的值是透過 = 傳遞,就是直接 assign 到那個位址,所以等同於常量。但是如果是物件,它所保存的則是它指向的位址。
const constant = 'intital';
constant = 'assign to constant error'; // TypeError: Assignment to constant variable
const foo = {}
foo.property = 'first property'
console.log(foo.property) // first property
foo = {} // TypeError: Assignment to constant variable
let 作用域(Scope)是在特定區塊(block)內,出了區塊就無效
這裏要介紹一個名詞,叫做 Temporal Dead Zone(TDZ),暫時死區,它會發生於在宣吿變數或常數前,就去存取這項變數,而跳出 ReferenceError 的例外;但如果是在 var 宣告前就存取對應變數,則會得到undefined。
if (true) {
tmp = 'TDZ ReferenceError'; // ReferenceError
console.log(tmp); // ReferenceError
let tmp;
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
console.log(temp) // ReferenceError,temp作用域只在 if (true){} 內
variable的簡寫,可以理解成變量的意思,在 ES6 裡主要用來升級成全局變量
當年我們都在 var 上踩過的雷:
console.log(temp); // undefined
var temp;
console.log(temp); // undefined
temp = 'test';
console.log(temp); // test
for (var i = 0; i < 5; i++) {
setTimeout(
function() {
console.log(i)
}, 1000
);
}
// 5,5,5,5,5
因為 var 會將 i 設定為全域變數,透過 for 累加,而 for 內部的異步事件會去註冊起來,直到 i 跑完了才停止,並且顯示出來。早期會透由閉包(Closure)處理,但現在可以用 let,因為受區塊引響,所以 for (let i...)的循環在迭代時都會為 i 建立新的綁定。
var ineedconstant = 'test';
ineedconstant=9999; // 值就直接被蓋過